from utils.ReadUtil import read_util
from utils.log_util import logger
import requests, random, string, json, base64, pymysql, re, os
from bs4 import BeautifulSoup


# 自定义异常类
class CaptchaError(Exception):
    pass


class public_server_utils:

    def __init__(self):
        self.oldsession = requests.Session()
        self.sessions = {}  # 存储用户会话
        # self.base_url = "https://testadmin.xkb365.com" 替换为实际的基础 URL
        self.base_url = read_util.read_data()['接口域名地址']['后台测试地址']  # 替换为实际的基础 URL
        self.current_phone = None
        self.connection = None

    def get_request(self, url, params=None, log=True):
        """统一的 GET 请求方法"""
        url = self.base_url + url
        try:
            session = self.get_current_session()  # 获取当前会话
            response = session.get(url, params=params)
            response.raise_for_status()  # 检查响应状态码
            if log:
                self.log_api_request_response(url, params, response)
                return response
            else:
                return response
        except requests.RequestException as e:
            logger.exception(f"接口地址{url}请求失败,请求参数{params}: {e}")
            return None

    def post_request(self, url, data=None, log=True):
        """统一的 POST 请求方法"""
        url = self.base_url + url
        try:
            session = self.get_current_session()  # 获取当前会话
            response = session.post(url, data=data)
            response.raise_for_status()  # 检查响应状态码
            if log:
                self.log_api_request_response(url, data, response)
                return response
            else:
                return response
        except requests.RequestException as e:
            logger.exception(f"接口地址{url}请求失败,请求参数{data}: {e}")
            return None

    def get_current_session(self):
        """获取当前的用户会话"""
        current_phone = self.current_phone if hasattr(self, 'current_phone') else None
        return self.sessions.get(current_phone)

    # def extract_cookies_from_request(self, url, phone='15917614074', password='123456'):
    #     """
    #     提取 JSESSIONID 并返回。
    #     """
    #     with sync_playwright() as p:
    #         # 使用 chromium 而不是 firefox，可能会更快
    #         browser = p.chromium.launch(headless=True)
    #         context = browser.new_context()
    #
    #         jsessionid_value = None  # 用于存储 JSESSIONID
    #
    #         def handle_request(route):
    #             nonlocal jsessionid_value  # 声明使用外部变量
    #             request_headers = route.request.headers
    #             cookie_header = request_headers.get('cookie')
    #             if cookie_header:
    #                 context.unroute('**/*', handle_request)  # 取消拦截
    #                 jsessionid_value = cookie_header  # 提取 Cookie
    #             route.continue_()
    #
    #         # 设置请求拦截器
    #         context.route('**/*', handle_request)
    #
    #         page = context.new_page()
    #
    #         # 执行登录操作
    #         user_ui.perform_login(page, phone, password)
    #
    #         # 访问目标页面以触发 Cookie 提取
    #         page.goto(url)
    #         page.wait_for_load_state('networkidle', timeout=5000)  # 缩短等待时间
    #
    #         browser.close()
    #
    #         return jsessionid_value  # 返回提取的 Cookie

    @staticmethod
    def generate_random_string(rando_name="测试课程", length=6):
        # 从大写字母、小写字母和数字中随机选择字符
        characters = string.ascii_letters  # 包含所有大小写字母
        return rando_name + ''.join(random.choice(characters) for _ in range(length))

    @staticmethod
    def verification_code():
        """
        识别验证码并返回识别结果。
        """
        with open("captcha_image.jpeg", 'rb') as f:
            base64_data = base64.b64encode(f.read())
        b64 = base64_data.decode()

        data = {"username": "ayin", "password": "Qz6528608", "typeid": 1003, "image": b64}
        result = json.loads(requests.post("http://api.ttshitu.com/predict", json=data).text)

        if result['success']:
            return result["data"]["result"]
        else:
            return result["message"]

    def get_img_code(self, session):
        # 获取图片验证码二进制文本
        image_response = session.get(url="https://testadmin.xkb365.com/captcha")
        # 将图片数据写入文件
        with open("captcha_image.jpeg", 'wb') as file:
            file.write(image_response.content)
        # 生成验证码并返回
        return self.verification_code()

    def getAppImgCode(self, base64_data):
        # 去除数据URI前缀
        base64_data = base64_data.split(",")[1]  # 提取`base64`部分

        # 检查Base64数据是否符合规则，添加填充符号
        missing_padding = len(base64_data) % 4
        if missing_padding:
            base64_data += '=' * (4 - missing_padding)

        # 解码Base64数据
        image_data = base64.b64decode(base64_data)
        # 将解码后的数据写入文件
        with open("captcha_image.jpeg", 'wb') as file:
            file.write(image_data)
        # 生成验证码并返回
        return self.verification_code()

    def save_image_from_url(self, image_url, save_path):
        """
        从 URL 下载图片并保存为文件。

        :param image_url: 图片的 URL
        :param save_path: 保存图片的文件路径
        """
        # 发送 GET 请求获取图片数据
        response = requests.get(image_url)

        # 确保请求成功
        if response.status_code == 200:
            # 将图片数据写入文件
            with open(save_path, 'wb') as file:
                file.write(response.content)
        else:
            print(f"获取图片失败，状态码: {response.status_code}")

    def login_background(self, login_phone, login_password):
        try:
            # 检查用户会话是否已存在，若不存在则创建一个新的 Session
            if login_phone not in self.sessions:
                self.sessions[login_phone] = requests.Session()

            session = self.sessions[login_phone]
            self.current_phone = login_phone  # 记录当前用户手机号

            # 使用统一的 GET 请求方法请求登录页面
            login_page_response = self.get_request(url="/loginpage.html")

            # 获取当前会话的 cookies
            if login_page_response is not None:
                # 将登录页面的 cookies 存入当前会话
                session.cookies.update(login_page_response.cookies)

            # 登录接口请求参数
            login_data = {
                "autoLogin": "2",
                "loginName": login_phone,
                "loginPassword": login_password,
                "kaptchaCode": self.get_img_code(session)  # 使用当前的 session 获取验证码
            }
            # 使用统一的 POST 请求方法进行登录
            response = self.post_request(url="/login.html", data=login_data)

            if response is not None and response.status_code == 200:
                # logger.debug(f"{login_phone}登录请求成功，响应状态码：{response.status_code}")
                # print(f"{login_phone}登录请求成功，响应状态码：", response.status_code)
                # print('------------------------------')
                return session  # 返回当前的会话
            else:
                logger.error("登录请求失败，状态码：", response.status_code if response else "无响应")
                # print("登录请求失败，状态码：", response.status_code if response else "无响应")
                return None
        except Exception as e:
            raise CaptchaError(f"登录后台账号{login_phone}失败: {e}") from e

    def execute_sql_function(self, sql):
        # 数据库连接配置
        config = {
            'host': read_util.read_data()['数据库']['host'],
            'user': read_util.read_data()['数据库']['user'],
            'password': read_util.read_data()['数据库']['password'],
            'port': read_util.read_data()['数据库']['port'],  # MySQL 默认端口
        }

        # 连接到数据库
        try:
            self.connection = pymysql.connect(**config)
            print("成功连接到数据库")

            # 创建一个游标对象
            with self.connection.cursor() as cursor:
                # 执行 UPDATE 语句
                # sql = f"UPDATE `xkb_prod_backup`.`course_recommended` SET `is_show` = 2 WHERE `title` = '国庆去哪里玩'"
                cursor.execute(sql)

                # 获取受影响的行数
                affected_rows = cursor.rowcount
                print(f"受影响的行数: {affected_rows}")

                # 提交事务，如果你没有设置自动提交的话
                self.connection.commit()

        except pymysql.MySQLError as e:
            print(f"连接数据库时发生错误: {e}")

        finally:
            # 关闭连接
            if self.connection:
                self.connection.close()
                print("数据库连接已关闭")

    @staticmethod
    def get_button_value_from_response(html_content, string_name, button_name):
        # 解析 HTML
        soup = BeautifulSoup(html_content, 'html.parser')

        # 查找并提取按钮的 detail 参数值
        for button in soup.find_all('button'):
            if button.get_text(strip=True) == f'{string_name}':
                onclick_value = button['onclick']
                # print(f"Found button with onclick: {onclick_value}")  # 调试输出

                # 使用正则表达式提取 button_name 的参数值
                detail_value = re.search(rf"{button_name}\('([^']+)", onclick_value)  # 可选的第二个参数
                if detail_value:
                    # 提取第一个参数值
                    param1 = detail_value.group(1)  # 第一个参数
                    return param1
                #     if detail_value.group(2):
                #         param2 = detail_value.group(2)  # 第二个参数（如果存在）
                #         print("提取的第二个参数值:", param2)  # 输出第二个参数
                #     else:
                #         print("未找到第二个参数值")
                # else:
                #     print("未找到 detail 值")

    @staticmethod
    def get_input_value_from_response(html_content, class_name, input_name):
        # 创建 BeautifulSoup 对象
        soup = BeautifulSoup(html_content, 'html.parser')

        # 查找 input 标签
        input_tag = soup.find('input', {'class': f'{class_name}'})

        # 获取 value 属性
        if input_tag:
            value = input_tag.get(f'{input_name}')
            return value
        else:
            print("没有找到 input 标签")

    @staticmethod
    def raise_captcha_error(message):
        raise CaptchaError(message)

    @staticmethod
    def log_api_request_response(url, params, response):
        """
        记录API请求和响应的日志。

        :param url: 请求的接口地址
        :param params: 请求参数
        :param response: 请求响应
        """
        logger.info(f"请求地址--------{url}")
        logger.info(f"请求参数--------{params}")
        logger.info(f"请求响应--------{response}")
        logger.info("")

    @staticmethod
    def handle_exception(e, message):
        logger.error(message, exc_info=True)  # 记录日志
        raise CaptchaError(f"{message}: {e}") from e  # 抛出新的异常


server_utils = public_server_utils()

# if __name__ == "__main__":
#     try:
#         # 获取图形验证码照片
#         captcha_response = self.app_getCaptcha()
#     except Exception as e:
#         raise CaptchaError(f"获取图形验证码照片失败: {e}")

# print(123)
# print(server_utils.raise_captcha_error("报错啦"))
